package com.example.thread.base.demo2;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


/**
 * @author LiYuhang
 * @version 0.1
 * @application
 * @Date 2020/8/14 11:02
 */
@Slf4j(topic = "demo2_3")
public class demo2_3 {

    /**
     * corePoolSize
     * 核心池的大小，这个参数跟后面讲述的线程池的实现原理有非常大的关系。在创建了线程池后，默认情况下，线程池中并没有任何线程，
     * 而是等待有任务到来才创建线程去执行任务，除非调用了prestartAllCoreThreads()或者prestartCoreThread()方法，
     * 从这2个方法的名字就可以看出，是预创建线程的意思，即在没有任务到来之前就创建corePoolSize个线程或者一个线程。
     * 默认情况下，在创建了线程池后，线程池中的线程数为0，当有任务来之后，就会创建一个线程去执行任务，
     * 当线程池中的线程数目达到corePoolSize后，就会把到达的任务放到缓存队列当中；
     * <p>
     * maximumPoolSize 线程池最大线程数
     * <p>
     * keepAliveTime
     * <p>
     * 表示线程没有任务执行时最多保持多久时间会终止。默认情况下，只有当线程池中的线程数大于corePoolSize时，keepAliveTime才会起作用，
     * 直到线程池中的线程数不大于corePoolSize，即当线程池中的线程数大于corePoolSize时，如果一个线程空闲的时间达到keepAliveTime，则会终止，
     * 直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法，在线程池中的线程数不大于corePoolSize时，
     * keepAliveTime参数也会起作用，直到线程池中的线程数为0；
     * <p>
     * unit 参数keepAliveTime的时间单位
     * TimeUnit.DAYS;               //天
     * TimeUnit.HOURS;             //小时
     * TimeUnit.MINUTES;           //分钟
     * TimeUnit.SECONDS;           //秒
     * TimeUnit.MILLISECONDS;      //毫秒
     * TimeUnit.MICROSECONDS;      //微妙
     * TimeUnit.NANOSECONDS;       //纳秒
     * <p>
     * <p>
     * workQueue 一个阻塞队列，用来存储等待执行的任务，这个参数的选择也很重要，会对线程池的运行过程产生重大影响
     * ArrayBlockingQueue; 基于数组的先进先出队列，此队列创建时必须指定大小；
     * LinkedBlockingQueue; 基于链表的先进先出队列，如果创建时没有指定此队列大小，则默认为Integer.MAX_VALUE；
     * SynchronousQueue; ：这个队列比较特殊，它不会保存提交的任务，而是将直接新建一个线程来执行新来的任务。
     * 一般使用LinkedBlockingQueue和Synchronous。线程池的排队策略与BlockingQueue有关
     * <p>
     * threadFactory 线程工厂，主要用来创建线程；
     * handler 表示当拒绝处理任务时的策略，有以下四种取值
     * <p>
     * ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
     * ThreadPoolExecutor.DiscardPolicy：也是丢弃任务，但是不抛出异常。
     * ThreadPoolExecutor.DiscardOldestPolicy：丢弃队列最前面的任务，然后重新尝试执行任务（重复此过程）
     * ThreadPoolExecutor.CallerRunsPolicy：由调用线程处理该任务
     */

    public static final Integer CORE_POOR_SIZE = 5;

    public static final Integer MAX_POOR_SIZE = 20;

    public static final Long KEEP_ALIVE_TIME = 20L;

    public static final BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(128);

    public static final ThreadFactory threadFactory = Executors.defaultThreadFactory();

    private static final RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();

    private static  final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(CORE_POOR_SIZE,MAX_POOR_SIZE,KEEP_ALIVE_TIME,TimeUnit.SECONDS,queue,threadFactory,handler);

    public static void main(String[] args) {
        for (int i = 0; i <100 ; i++) {
            int finalI = i;
            threadPoolExecutor.execute(()->{
                log.info("线程名称；{}，执行到第{}次",Thread.currentThread().getName(),finalI);
            });
        }
        threadPoolExecutor.shutdown();
    }
}
